package com.letu.aopcache.manager;

import com.alibaba.fastjson.JSONObject;
import com.letu.annotation.annotation.cache.Cache;
import com.letu.aopcache.MethodCacheKeyBuilder;
import com.letu.aopcache.aop.CacheAopProxyChain;
import com.letu.aopcache.exception.CacheCenterConnectionException;
import com.letu.aopcache.model.*;
import com.letu.aopcache.parser.AbstractScriptParser;
import com.letu.aopcache.util.MSetParam;
import com.letu.cache.repository.CacheOps;
import com.letu.cache.repository.CaffeineCacheOps;
import com.letu.core.model.CacheKey;
import com.letu.core.model.CacheKeyBuilder;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * 缓存关联关系 管理类
 */
@Slf4j
public class RelatedCacheManager {
    public static List<String> paramsList = Arrays.asList("id", "projectId", "subsystemId", "tenantId", "echoMap", "updatedBy", "createBy", "isDeleted");
    private final ICacheManager cacheManager;
    /**
     * 表达式解析器
     */
    private final AbstractScriptParser scriptParser;
    private final CacheOps cacheOps;

    private final CaffeineCacheOps caffeineCacheOps;

    private final AutoLoadConfig config;


    public RelatedCacheManager(ICacheManager cacheManager, AbstractScriptParser scriptParser, CacheOps cacheOps, AutoLoadConfig config, CaffeineCacheOps caffeineCacheOps) throws IllegalArgumentException {
        if (null == cacheManager) {
            throw new IllegalArgumentException("cacheManager is null");
        }
        if (null == scriptParser) {
            throw new IllegalArgumentException("scriptParser is null");
        }
        this.cacheManager = cacheManager;
        this.scriptParser = scriptParser;
        this.cacheOps = cacheOps;
        this.config = config;
        this.caffeineCacheOps = caffeineCacheOps;
    }


    /**
     * 保存关联关系缓存
     *
     * @param cache               缓存自定义注解
     * @param methodMsg           方法基础信息
     * @param cacheWrapper        返回值类
     * @param relatedCacheKeyList 关联关系key集合
     * @param interfaceCacheKey   接口缓存key
     * @throws Exception
     */
    public void writeCache(Cache cache, MethodMsg methodMsg, CacheWrapper<Object> cacheWrapper, List<CacheKeyTO> relatedCacheKeyList, CacheKeyTO interfaceCacheKey) throws Exception {
        if (null == cacheWrapper || cacheWrapper.getIds() == null || cacheWrapper.getIds().isEmpty()) {
            return;
        }
        List<MSetParam> params = new ArrayList<>();
        CacheWrapper<Object> objectCacheWrapper = (CacheWrapper<Object>) cacheWrapper.clone();
        objectCacheWrapper.setCacheObject(null);
        objectCacheWrapper.setObjectList(null);
        //暂时不记录参数和方法名，如果以后用于自动加载可以存
        objectCacheWrapper.setIds(null);
        objectCacheWrapper.setArgs(null);
        objectCacheWrapper.setHeader(null);
        objectCacheWrapper.setClassName(null);
        for (CacheKeyTO cacheKeyTO : relatedCacheKeyList) {
//            objectCacheWrapper.setInterfaceKey(interfaceCacheKey.getKey());
            params.add(new MSetParam(cacheKeyTO, objectCacheWrapper));
        }
        int size = params.size();
        if (size == 1) {
            MSetParam param = params.get(0);
//            cacheManager.setCache(param.getCacheKey(), param.getResult(), null);
            //减轻数据
            CacheWrapper<Object> result = param.getResult();
            result.setReturnType(null);
            result.setMethodName(null);
            result.setInterfaceKey(null);
            result.setObjectClassName(null);
            cacheManager.setCache(param.getCacheKey(), result, null);

        } else if (size > 1) {
            cacheManager.mset(null, params);
        }
    }

    /**
     * 保存关联关系缓存 Caffeine
     *
     * @param cache               缓存自定义注解
     * @param methodMsg           方法基础信息
     * @param cacheWrapper        返回值类
     * @param relatedCacheKeyList 关联关系key集合
     * @param interfaceCacheKey   接口缓存key
     * @throws Exception
     */
    public void writeCacheOfCaffeine(Cache cache, MethodMsg methodMsg, CacheWrapper<Object> cacheWrapper, List<CacheKeyTO> relatedCacheKeyList, CacheKeyTO interfaceCacheKey) throws Exception {
        if (null == cacheWrapper || cacheWrapper.getIds() == null || cacheWrapper.getIds().isEmpty()) {
            return;
        }
        List<MSetParam> params = new ArrayList<>();
        CacheWrapper<Object> objectCacheWrapper = (CacheWrapper<Object>) cacheWrapper.clone();
        objectCacheWrapper.setCacheObject(null);
        objectCacheWrapper.setObjectList(null);
        //暂时不记录参数和方法名，如果以后用于自动加载可以存
        objectCacheWrapper.setIds(null);
        objectCacheWrapper.setArgs(null);
        objectCacheWrapper.setHeader(null);
        objectCacheWrapper.setClassName(null);
        for (CacheKeyTO cacheKeyTO : relatedCacheKeyList) {
//            objectCacheWrapper.setInterfaceKey(interfaceCacheKey.getKey());
            params.add(new MSetParam(cacheKeyTO, objectCacheWrapper));
        }
        int size = params.size();
        if (size == 1) {
            MSetParam param = params.get(0);
//            cacheManager.setCache(param.getCacheKey(), param.getResult(), null);
            //减轻数据
            CacheWrapper<Object> result = param.getResult();
            result.setReturnType(null);
            result.setMethodName(null);
            result.setInterfaceKey(null);
            result.setObjectClassName(null);
            cacheManager.setCacheOfCaffeine(param.getCacheKey(), result, null);

        } else if (size > 1) {
            cacheManager.msetOfCaffeine(null, params);
        }
    }


    /**
     * 查询关联关系缓存
     *
     * @param cacheWrapper 返回值类
     * @throws Exception
     */
    public List<CacheWrapper<Object>> queryCache(CacheWrapper<Object> cacheWrapper, List<CacheKeyTO> relatedKeyTo) throws Exception {
        if (null == cacheWrapper || cacheWrapper.getIds() == null
                || cacheWrapper.getIds().isEmpty()
                || relatedKeyTo == null || relatedKeyTo.isEmpty()) {
            return null;
        }
        List<CacheKey> cacheKeyList = new ArrayList<>();
        for (CacheKeyTO cacheKeyTO : relatedKeyTo) {
            cacheKeyList.add(new MethodCacheKeyBuilder().key(cacheKeyTO.getNamespace(), cacheKeyTO.getKey()));
        }
        List<CacheWrapper<Object>> dataList = cacheOps.mGetByCacheKey(cacheKeyList);
        return dataList;
    }


    /**
     * 查询关联关系缓存
     *
     * @param cacheWrapper 返回值类
     * @throws Exception
     */
    public List<CacheWrapper<Object>> queryCacheOfCaffeine(CacheWrapper<Object> cacheWrapper, List<CacheKeyTO> relatedKeyTo) throws Exception {
        if (null == cacheWrapper || cacheWrapper.getIds() == null
                || cacheWrapper.getIds().isEmpty()
                || relatedKeyTo == null || relatedKeyTo.isEmpty()) {
            return null;
        }
        List<CacheWrapper<Object>> dataList = new ArrayList<>();

        for (CacheKeyTO cacheKeyTO : relatedKeyTo) {
            CacheKey cacheKey = new MethodCacheKeyBuilder().key(cacheKeyTO.getNamespace(), cacheKeyTO.getKey());
            CacheWrapper<Object> cacheWrapper1 = caffeineCacheOps.get(cacheKey);
            dataList.add(cacheWrapper1);
        }
        return dataList;
    }


    /**
     * 删除关联关系缓存
     *
     * @param ids ids
     * @throws Exception
     */
    public void delCache(List<Long> ids, String objectClassName) throws Exception {
        if (ids == null || ids.isEmpty()) {
            return;
        }
        for (Long id : ids) {
            CacheKey cacheKey = new MethodCacheKeyBuilder().key(objectClassName + ":" + CacheWayEnum.HASH.getCode() + ":" + id);
            cacheOps.delVague(cacheKey.getKey() + ":*");
        }
    }

    /**
     * 删除关联关系缓存
     *
     * @param objectClassName 类名称
     * @throws Exception
     */
    public void delCache(String objectClassName) throws Exception {
        CacheKey cacheKey = new MethodCacheKeyBuilder().key(objectClassName);
        cacheOps.delVague(cacheKey.getKey() + ":" + CacheWayEnum.HASH.getCode() + ":*");
    }

    /**
     * 删除关联关系缓存
     *
     * @param objectClassName 类名称
     * @throws Exception
     */
    public void delCacheOfMagic(String objectClassName, JSONObject jsonObject, List<String> clearTargetKeyParam) throws Exception {
        List<String> keyList = new ArrayList<>();
        for (String key : jsonObject.keySet()) {
            if (!clearTargetKeyParam.contains(key)) {
                continue;
            }
            Object object = jsonObject.get(key);
            if (object != null) {
                String cacheKeyStr = "";
//                cacheKeyStr = config.getNamespace() + ":" + objectClassName + ":"
//                        + CacheWayEnum.MAGIC.getCode() + ":"
//                        + key + ":"
//                        + "eq:"
//                        + object.toString() + ":*";


                cacheKeyStr = config.getNamespace() + ":" + objectClassName + ":"
                        + CacheWayEnum.MAGIC.getCode() + ":"
                        + key + ":"
                        + "eq:"
                        + object.toString();


                CacheKey cacheKey = new MethodCacheKeyBuilder().key(cacheKeyStr);
                keyList.add(cacheKey.getKey());

                //like
//                cacheKeyStr = config.getNamespace() + ":" + objectClassName + ":"
//                        + CacheWayEnum.MAGIC.getCode() + ":"
//                        + key + ":"
//                        + "like:*";
//                cacheKey = new MethodCacheKeyBuilder().key(cacheKeyStr);
//                keyList.add(cacheKey.getKey());

            }
        }
        String[] toBeStored = keyList.toArray(new String[keyList.size()]);
        long l = System.currentTimeMillis();
        cacheOps.delVague(toBeStored);
        log.error("清除缓存耗时：{}",System.currentTimeMillis() - l);
    }
}
